Docker存储驱动 您所在的位置:网站首页 docker rootfs 精简 Docker存储驱动

Docker存储驱动

2023-07-16 01:00| 来源: 网络整理| 查看: 265

Docker 的 devicemapper 存储驱动利用了内核 device mapper 的 thin provisioning(自动精简配置)和 snapshotting(快照)的能力来管理镜像和容器

devicemapper使用Docker专用的块设备,操作为块级而不是文件级。可以通过为Docker主机添加物理存储来扩充这些设备

这篇文章是对Docker官网中 devicemapper 存储驱动使用文档的翻译

配置使用devicemapperloop-lvm 模式

这个模式仅仅适用于测试。loopback(回路)设备非常慢并且资源敏感,他们在磁盘中创建的文件需要有固定大小,他们还会引入竞争。配置这种模式的步骤十分简单:

停止Docker服务 1sudo service docker stop 编辑/etc/docker/daemon.json 123{ "storage-driver": "devicemapper"} 开启Docker服务 1sudo service docker start docker info进行确认 123456789101112131415161718192021222324252627282930$ docker infoContainers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 0 Server Version: 17.03.1-ce Storage Driver: devicemapper Pool Name: docker-202:1-8413957-pool Pool Blocksize: 65.54 kB Base Device Size: 10.74 GB Backing Filesystem: xfs Data file: /dev/loop0 Metadata file: /dev/loop1 Data Space Used: 11.8 MB Data Space Total: 107.4 GB Data Space Available: 7.44 GB Metadata Space Used: 581.6 kB Metadata Space Total: 2.147 GB Metadata Space Available: 2.147 GB Thin Pool Minimum Free Space: 10.74 GB Udev Sync Supported: true Deferred Removal Enabled: false Deferred Deletion Enabled: false Deferred Deleted Device Count: 0 Data loop file: /var/lib/docker/devicemapper/data Metadata loop file: /var/lib/docker/devicemapper/metadata Library Version: 1.02.135-RHEL7 (2016-11-16)

Data loop file和Metadata loop file文件位于/var/lib/docker/devicemapper目录下,表明当前已经运行在loop-lvm模式下

direct-lvm 模式

生产环境中需要使用这种模式。这种模式使用块设备来创建 thin pool,这比 loopback(回环)设备更快、资源利用更有效,并且块设备能按需增长。但是配置也相对更复杂一些

1)让Docker来配置 direct-lvm 模式

如果使用Docker 17.06或者更高版本,Docker能够为我们管理块设备。这种方式适用于简单地配置,只能使用一个块设备。如果需要使用多个块设备,参考后面的手动配置部分

配置选项如下表:

Option Description Required? Default Example dm.directlvm_device 块设备的路径 Yes dm.directlvm_device="/dev/xvdf" dm.thinp_percent 用于数据存储的空间百分比 No 95 dm.thinp_percent=95 dm.thinp_metapercent 用于元数据存储的空间百分比 No 1 dm.thinp_metapercent=1 dm.thinp_autoextend_threshold lvm自动扩充thin pool的阈值百分比 No 80 dm.thinp_autoextend_threshold=80 dm.thinp_autoextend_percent 当发生自动扩充时,增加thin pool的存储空间的百分比 No 20 dm.thinp_autoextend_percent=20 dm.directlvm_device_force 是否格式化块设备,即使块设备上已经存在文件系统。如果设为false并且文件系统存在,将会报错 No false dm.directlvm_device_force=true

使用上面的选项来设置/etc/docker/daemon.json,然后重启Docker服务:

1234567891011{ "storage-driver": "devicemapper", "storage-opts": [ "dm.directlvm_device=/dev/xdf", "dm.thinp_percent=95", "dm.thinp_metapercent=1", "dm.thinp_autoextend_threshold=80", "dm.thinp_autoextend_percent=20", "dm.directlvm_device_force=false" ]} 2)手动配置 direct-lvm 模式 选择一个大小足够的块设备 停止Docker服务 1sudo service docker stop

安装下列包

RHEL/CentOS:device-mapper-persistent-data,lvm2和所有依赖 Ubuntu/Debian:thin-provisioning-tools,lvm2和所有依赖

使用pvcreate命令创建PV(物理卷)

123$ sudo pvcreate /dev/xvdfPhysical volume "/dev/xvdf" successfully created. 使用vgcreate命令创建一个名为docker的VG(卷组) 123$ sudo vgcreate docker /dev/xvdfVolume group "docker" successfully created 使用lvcreate命令创建2个名为thinpool和thinpoolmeta的LV(逻辑卷),这2个卷都使用docker卷组。最后一个参数指定了可用于自动扩充的空闲空间占VG的百分比 1234567$ sudo lvcreate --wipesignatures y -n thinpool docker -l 95%VGLogical volume "thinpool" created.$ sudo lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VGLogical volume "thinpoolmeta" created. 使用lvconvert将逻辑卷thinpool转换为一个 thin pool,将逻辑卷thinpoolmeta指定为 thin pool 的元数据逻辑卷 12345678910$ sudo lvconvert -y \--zero n \-c 512K \--thinpool docker/thinpool \--poolmetadata docker/thinpoolmetaWARNING: Converting logical volume docker/thinpool and docker/thinpoolmeta tothin pool's data and metadata volumes with metadata wiping.THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)Converted docker/thinpool to thin pool. 编辑lvm profile文件配置thin pool的自动扩展。然后使用lvchange命令使配置文件中的配置生效: 12345678910$ sudo vim /etc/lvm/profile/docker-thinpool.profileactivation { thin_pool_autoextend_threshold=80 thin_pool_autoextend_percent=20}$ sudo lvchange --metadataprofile docker-thinpool docker/thinpoolLogical volume docker/thinpool changed. 开启逻辑卷监视。没有这一步的话即使编辑好了profile配置文件也无法触发自动扩充 1234$ sudo lvs -o+seg_monitorLV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert Monitorthinpool docker twi-a-t--- 95.00g 0.00 0.01 monitored 备份Dokcer根目录中的数据,然后使用新创建的 LVM pool 来存储镜像和容器 12$ mkdir /var/lib/docker.bk$ mv /var/lib/docker/* /var/lib/docker.bk 编辑/etc/docker/daemon.json,并配置devicemapper需要的选项 12345678{ "storage-driver": "devicemapper", "storage-opts": [ "dm.thinpooldev=/dev/mapper/docker-thinpool", "dm.use_deferred_removal=true", "dm.use_deferred_deletion=true" ]} 开启Docker服务 1sudo service docker start 使用docker info进行确认: 12345678910111213141516171819202122232425262728$ docker infoContainers: 0 Running: 0 Paused: 0 Stopped: 0Images: 0Server Version: 17.03.1-ceStorage Driver: devicemapper Pool Name: docker-thinpool Pool Blocksize: 524.3 kB Base Device Size: 10.74 GB Backing Filesystem: xfs Data file: Metadata file: Data Space Used: 19.92 MB Data Space Total: 102 GB Data Space Available: 102 GB Metadata Space Used: 147.5 kB Metadata Space Total: 1.07 GB Metadata Space Available: 1.069 GB Thin Pool Minimum Free Space: 10.2 GB Udev Sync Supported: true Deferred Removal Enabled: true Deferred Deletion Enabled: true Deferred Deleted Device Count: 0 Library Version: 1.02.135-RHEL7 (2016-11-16)

如果配置正确的话,Data file和Metadata file会是空,并且Pool Name是docker-thinpool

为运行中的设备扩容

不要仅仅依赖于LVM的自动扩容机制。VG自动扩容,但是LV可能还是满的。可以使用lvs或lvs -a查看LV的空闲空间

可以使用journalctl查看LVM的日志:

1$ journalctl -fu dm-event.service

如果重复遇到某个问题,可以在/etc/docker.daemon.json中设置dm.min_free_space选项,比如设置成10(表示百分比),从而确保当空闲空间不足10%时操作会失败并返回提示信息

改变 loop-lvm 模式设备的大小

有下列2种方法:

1. 使用社区共享的device_tool.go脚本(链接)。使用这个工具最为方便,但不一定奏效

1)首先将链接中的仓库克隆,然后重命名为contrib/docker-device-tool。接着按照README.md中的说明编译工具

2)使用类似$ ./device_tool resize 200GB这样的指令扩容

2. 使用操作系统工具

在 loop-lvm 模式下,一个 loopback(回环)设备被用于存储数据,另一个 loopback(回环)设备被用于存储元数据。这种模式仅适合测试,因为性能和稳定性都不好

假设原来的 loopback(回环)设备大小为100GB,现在要扩容到200GB

1)查看2个 loopback(回环)设备:

12345$ sudo ls -lh /var/lib/docker/devicemapper/total 1175492-rw------- 1 root root 100G Mar 30 05:22 data-rw------- 1 root root 2.0G Mar 31 11:17 metadata

2)使用truncate命令将数据文件的大小修改成200G

1$ sudo truncate -s 200G /var/lib/docker/devicemapper/data

3)再次查看2个 loopback(回环)设备:

12345$ sudo ls -lh /var/lib/docker/devicemapper/total 1.2G-rw------- 1 root root 200G Apr 14 08:47 data-rw------- 1 root root 2.0G Apr 19 13:27 metadata

4)loopback 文件已经在磁盘上发生了改变,但是内存中没有。列出内存中 loopback 设备的大小,重载,然后再次列出它的大小,此时内存中的大小也得到更新:

123456789$ echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ]100$ sudo losetup -c /dev/loop0$ echo $[ $(sudo blockdev --getsize64 /dev/loop0) / 1024 / 1024 / 1024 ]200

5)重载 devicemapper thin pool

123456789101112131415161718# a)首先得到 thin pool 的名字$ sudo dmsetup status | grep ' thin-pool ' | awk -F ': ' {'print $1'}docker-8:1-123141-pool# b)dump device mapper table for the thin pool$ sudo dmsetup table docker-8:1-123141-pool0 209715200 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing# c)使用上一步输出中的第2个域计算 thin pool 所有的扇区。如果扩容为200G,即原来的2倍,那么扇区数也变成原来的2倍,即419430400# d)使用新的扇区数重载 thin pool$ sudo dmsetup suspend docker-8:1-123141-pool$ sudo dmsetup reload docker-8:1-123141-pool --table '0 419430400 thin-pool 7:1 7:0 128 32768 1 skip_block_zeroing'$ sudo dmsetup resume docker-8:1-123141-pool 改变 direct-lvm 模式设备的大小

首先要附加一块新的块设备,假设这块新的设备为/dev/xvdg

使用pvdisplay找到当前被 thin pool 使用的PV和VG: 1234$ sudo pvdisplay |grep 'VG Name'PV Name /dev/xvdfVG Name docker 执行vgextend命令使用新的设备/dev/xvdg来扩充VG: 1234$ sudo vgextend docker /dev/xvdgPhysical volume "/dev/xvdg" successfully created.Volume group "docker" successfully extended 使用下列命令扩充docker/thinpool LV(逻辑卷)。下面的命令会使用所以100%的可用空间。如果要扩充元数据 thin pool, 使用docker/thinpool_tmeta代替docker/thinpool: 1234$ sudo lvextend -l+100%FREE -n docker/thinpoolSize of logical volume docker/thinpool_tdata changed from 95.00 GiB (24319 extents) to 198.00 GiB (50688 extents).Logical volume docker/thinpool_tdata successfully resized. 查看docker info输出中的Data Space Available域确认扩容完成: 1234567891011121314Storage Driver: devicemapper Pool Name: docker-thinpool Pool Blocksize: 524.3 kB Base Device Size: 10.74 GB Backing Filesystem: xfs Data file: Metadata file: Data Space Used: 212.3 MB Data Space Total: 212.6 GB Data Space Available: 212.4 GB Metadata Space Used: 286.7 kB Metadata Space Total: 1.07 GB Metadata Space Available: 1.069 GB

如果重启主机后发现Docker服务启动失败,然后报错:”Non existing device“,需要调用命令sudo lvchange -ay docker/thinpool来重新激活逻辑卷

devicemapper如何工作

使用 lsblk 命令查看设备和 thin pool :

12345678910$ sudo lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTxvda 202:0 0 8G 0 disk└─xvda1 202:1 0 8G 0 part /xvdf 202:80 0 100G 0 disk├─docker-thinpool_tmeta 253:0 0 1020M 0 lvm│ └─docker-thinpool 253:2 0 95G 0 lvm└─docker-thinpool_tdata 253:1 0 95G 0 lvm └─docker-thinpool 253:2 0 95G 0 lvm

使用 mount 命令查看容器使用的挂载点:

12$ mount | grep devicemapper/dev/xvda1 on /var/lib/docker/devicemapper type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

当使用devicemapper存储驱动时,Docker将镜像和层数据存储在 thinpool 中,然后通过将它们挂载在/var/lib/docker/devicemapper/的子目录下来暴露给容器

磁盘中的镜像和容器层 /var/lib/docker/devicemapper/metadata/目录包含 devicemapper 配置的元数据以及每个镜像和容器层的元数据。devicemapper 使用快照,这些元数据包含这些快照的信息,文件格式为JSON /var/lib/docker/devicemapper/mnt/目录为每个镜像和容器层创建了一个挂载点。镜像层的挂载点为空,而容器层的挂载点展示了容器的文件系统 镜像的分层与共享

devicemapper 存储驱动使用专用的块设备,而不是格式化的文件系统。块级操作可以为CoW操作带来最大的性能

快照

devicemapper 的另一个特征是快照。它将每一层引入的差异存储为非常小的,轻量级的 thin pools。快照提供很多好处:

多个容器共享的层只在磁盘中存储一次,除非它们可写 快照是CoW机制的一种实现。这意味着当一个文件或者目录被修改时,它们会被拷贝到容器的可写层然后再修改 因为操作是块级,所以可写层的多个块的修改可同时进行 快照能用OS级的备份工具来备份:拷贝/var/lib/docker/devicemapper/ 工作流

当使用 devicemapper 存储驱动时,所有和镜像及容器有关的对象被存储在/var/lib/docker/devicemapper/中,这个目录的后端是一个或多个块设备,如 loopback 设备或物理磁盘

基础设备是最底层的对象,也就是 thin pool。可以使用docker info查看,它包含了1个文件系统。这个基础设备是每个镜像和容器层的起点。这个基础设备是一个Device Mapper的详细实现,而不是一个Docker的层 关于基础设备和镜像及容器层的元数据以JSON格式存储在/var/lib/docker/devicemapper/metadata/中,它们都是CoW快照,意味着在和父层表现出差异之前,它们都是空 每个容器的可写层挂载在/var/lib/docker/devicemapper/mnt/目录中的一个挂载点上。每个镜像层和停止的容器在/var/lib/docker/devicemapper/mnt/中有一个空目录

每个镜像层是它下层的一个快照。每个镜像的最底层是pool中基础设备的一个快照。当运行一个容器时,会根据容器使用的镜像创建1个快照

容器中的读写读文件

读为块级。下图展示了读一个块(0x44f)的处理流程:

一个应用发起一个对块0x44f的读请求,因为容器是镜像的一个 thin snapshot,它并没有这个块,但是它有一个指向最近父镜像中这个块的指针,所以会从父镜像中读取这个块。这个块现在存在于容器的内存中

写文件 写一个新文件:将新数据写入容器是通过按需分配操作完成的。新文件的每个块都分配在容器的可写层中,然后对可写层中的块进行写 更新一个已有文件:文件相关的块从存有该文件的最近层读取。当容器写这个文件时,只有修改的块会被写到容器的可写层 删除一个文件或目录:当删除容器可写层中的文件或目录时,或者当镜像层删除1个位于父镜像层中的文件时,devicemapper存储驱动会拦截以后对该文件或目录的读取操作并响应”此文件不存在“ 写然后删除一个文件:如果容器先写一个文件,然后删除它,所以这些操作发生在容器的可写层。这种情况下,如果使用 direct-lvm 模式,块会被释放。如果使用 loop-lvm 模式,块不会被释放。这是不在生产环境中使用 loop-lvm 模式的另一个原因

性能与最佳实践性能 allocate-on demand(按需分配):devicemapper存储驱动使用按需分配操作从 thin pool 中分配新的块。每个块64KB,因此这是一个写使用的最小的空间 CoW性能影响:容器第一次修改1个特定块时,块被写入容器的可写层。因为这些写为块级而不是文件级,所以性能影响最小化。然而,写大量的块仍会对性能产生消极影响,此时,devicemapper可能比其他存储驱动表现出更差的性能。对于写密集的负载,应该使用数据卷 最佳实践 使用 direct-lvm 模式:loop-lvm模式不适用与生产环境 使用更快的存储介质:SSD提供更好的读写性能 内存使用:devicemapper比其他存储驱动使用更多的内存。每个启动的容器将一份或多份文件的拷贝装载到内存中,取决于相同文件中有多少个块在同一时刻被修改。由于内存压力,devicemapper存储驱动可能不适应与高密集型负载的使用场景 在写繁重的场景中使用数据卷:卷 bypass(旁路)了存储驱动,不会引入由 thin provisioning(自动精简配置)和 CoW 带来的潜在性能开销

其它资料 Docker基础技术:Devicemapper(可以使用命令模拟容器和镜像的分层结构) linux device mapper 原理与使用(介绍怎么删除 thin pool 中的设备)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有